<template>
  <div class="base">
    <canvas id="webgl"></canvas>
    <div class="pannel">
      <span>XZ：{{ x?.toFixed(2) }},{{ z?.toFixed(2) }}</span>
      <br />
      <span>注意：必须关闭相机缩放跟旋转</span>
    </div>
  </div>
</template>

<script setup>
import { nextTick, onMounted, onUnmounted, ref } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import utils from "@/utils";
import * as dat from "lil-gui";

onMounted(() => {
  console.log(utils);
  init();
});
const guiRef = ref();
const dotGetlistener = ref();
onUnmounted(() => {
  guiRef.value.destroy();
  document.removeEventListener('click', dotGetlistener.value)
  dotGetlistener.value = null;
})

const x = ref();
const z = ref();

const init = () => {
  // ----------------------------场景--------------------------
  // 创建场景
  const canvas = document.querySelector("#webgl");
  // 获取场景实例
  const scene = new THREE.Scene();
  // 场景渲染尺寸
  const baseBox = document.querySelector(".base");
  const sizes = {
    width: baseBox.clientWidth,
    height: baseBox.clientHeight,
  };
  // ----------------------------辅助线--------------------------
  let axesHelper = new THREE.AxesHelper(100);
  const gridHelper = new THREE.GridHelper(100, 100);
  scene.add(gridHelper);
  //   console.log(scene);
  // ----------------------------物体--------------------------
  // 几何体
  const geometry = new THREE.BoxGeometry(90, 1, 40);
  // 材质
  const material = new THREE.MeshBasicMaterial({
    color: 0xf5f5f5,
    transparent: true,
    opacity: 0.5,
  });
  // 合成网格模型
  const mesh = new THREE.Mesh(geometry, material);
  // 加入场景
  scene.add(mesh);

  //   const raycaster = new THREE.Raycaster();
  // ----------------------------监听网页拉伸--------------------------
  window.addEventListener("resize", () => {
    // Update sizes
    sizes.width = baseBox.clientWidth;
    sizes.height = baseBox.clientHeight;

    console.log(baseBox.clientWidth);
    // Update camera
    camera.aspect = sizes.width / sizes.height;
    camera.updateProjectionMatrix();

    // Update renderer
    renderer.setSize(sizes.width, sizes.height);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  });
  // --------------------------相机相关------------------------------
  // 基础相机
  const camera = new THREE.PerspectiveCamera(
    75,
    sizes.width / sizes.height,
    0.1,
    1000
  );

  scene.add(camera);

  // 相机控制器
  const controls = new OrbitControls(camera, canvas);
  //启用旋转
  controls.enableRotate = false;
  //禁止缩放
  controls.enableZoom = false;
  // 添加阻尼感
  controls.enableDamping = true;

  // --------------------------渲染------------------------------
  const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true,
  });

  renderer.setSize(sizes.width, sizes.height);
  //设置canvas的像素比为当前设备的屏幕像素比或者2之间的最小值，避免高分屏下模糊
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
  renderer.setClearColor("#90acc6");

  // --------------------------动画------------------------------
  const clock = new THREE.Clock();

  const tick = () => {
    // 内置时钟 解决不同设备运行动画速率不一致的问题
    const elapsedTime = clock.getElapsedTime();

    // Update controls
    controls.update();

    // Render
    renderer.render(scene, camera);

    // Call tick again on the next frame
    window.requestAnimationFrame(tick);
  };
  tick();

  // ----------------------------点击射线检测--------------------------
  dotGetlistener.value = (e) => {
    const result = utils.choose(e, sizes, camera, [mesh]); //射线拾取结果
    console.log(result[0].point.x);
    console.log(result[0].point.y);
    console.log(result[0].point.z);
    x.value = result[0].point.x;
    z.value = result[0].point.z;

    createMesh(result[0].point.x, result[0].point.z, scene);
  }
  document.addEventListener("dblclick", dotGetlistener.value);

  // --------------------------调试器------------------------------
  guiRef.value = new dat.GUI({
    width: 300,
  });
  const debugObject = {
    // 需要调试的内容
    view: 35,
    rotate: false,
    scale: false,
    reset: () => {
      camera.position.z = 0;
      camera.position.y = debugObject.view;
      camera.position.x = 0;
    },
    back: () => back(scene),
  };
  camera.position.z = 0;
  camera.position.y = debugObject.view;
  camera.position.x = 0;
  guiRef.value.add(debugObject, "reset").name("相机重置");
  guiRef.value.add(debugObject, "back").name("撤销");
  guiRef.value
    .add(debugObject, "view")
    .name("相机视野")
    .min(0)
    .max(200)
    .step(1)
    .onChange((e) => {
      camera.position.y = debugObject.view;
    });
  guiRef.value
    .add(debugObject, "rotate")
    .name("允许旋转")
    .onChange((e) => {
      controls.enableRotate = e;
    });
  guiRef.value
    .add(debugObject, "scale")
    .name("允许缩放")
    .onChange((e) => {
      controls.enableZoom = e;
    });
};

// 撤销生成的矩形
const back = (scene) => {
  scene.children.pop();
};

// 生成矩形 x,z-坐标 scene-场景
const createMesh = (x, z, scene) => {
  const geometry = new THREE.BoxGeometry(4, 0, 2);
  // 材质
  const material = new THREE.MeshBasicMaterial({
    color: 0x3963bc,
    transparent: true,
    opacity: 1,
  });
  // 合成网格模型
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.x = x;
  mesh.position.y = 0.6;
  mesh.position.z = z;
  scene.add(mesh);
  //   console.log(scene.children);
  //   return mesh
};

</script>
<style lang="scss" scoped>
.base {
  width: 100%;
  height: 100%;
  background-color: #ffffff;
  position: relative;

  #webgl {
    width: 100%;
    height: 100%;
  }

  .pannel {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 1;
    width: 300px;
    min-height: 60px;
    border-bottom-right-radius: 40px;
    background-color: #08245f;
    color: #fff;
    padding: 10px;
    font-size: 14px;
    @include flex(column, flex-start, flex-start);
  }
}
</style>